   #include <linux/module.h>
   #include <linux/fs.h>
   #include <linux/cdev.h>
   #include <linux/device.h>
   #include <asm/io.h>
   #include <asm/uaccess.h>
   #include <linux/init.h>
   #include <linux/uaccess.h>
   #include <linux/moduleparam.h>  
   #define BCM2711_GPIO_BASE   0xfe200000
   #define LED_ON  1
   #define LED_OFF 0
   #define GPFSEL0 (0x0/4)
   #define GPFSEL1 (0x4/4)
   #define GPFSEL2 (0x8/4)
   #define GPFSEL3 (0xc/4)
   #define GPFSEL4 (0x10/4)
   #define GPFSEL5 (0x14/4)
   #define GPSET0 (0x1c/4)
   #define GPSET1 (0x20/4)
   #define GPCLR0 (0x28/4)
   #define GPCLR1 (0x2c/4)
   static dev_t devno;          //设备号
   static int major;           //主设备号
   static int minor;          //次设备号 
   static struct cdev led_dev;
   static struct class *cls;
   static struct device *test_device;
   unsigned int *global_gpio = NULL;
static int led_open (struct inode *inode, struct file *filep)
{//open
	int sel0_value = 0;
	//实现对pin 4引脚 设为输出操作
	sel0_value = *(global_gpio+GPFSEL0);	
	sel0_value |= (1<<12);
	sel0_value &= ~(1<<13);
	sel0_value &= ~(1<<14);
	*(global_gpio+GPFSEL0) = sel0_value;

	printk(KERN_INFO"led_open sel0_value = 0x%x\n", sel0_value);
	return 0;
}
static ssize_t led_read(struct file *filep, char __user *buf, size_t len, loff_t *pos)
{
   printk(KERN_INFO"led_read \n");
   return 0;
 }
static ssize_t led_write(struct file *filep, const char __user *buf, size_t len, loff_t *pos)
{	//实现对pin 4引脚 高电平 低电平操作
	int set0_value = 0;
	char led_value = 0;
	unsigned long count = 1; 

	if(copy_from_user((void *)&led_value, buf, count))
	{
		return -1;
	}
	printk(KERN_ERR"led_write led_num =%d \n",led_value);
	if (led_value > 0)
	{
		set0_value = *(global_gpio+GPSET0);
		set0_value |= (1<<4);
		*(global_gpio+GPSET0) = set0_value;
		printk(KERN_ERR"0 write led_value =0x%x \n",set0_value);
	}
	else 
	{
		set0_value = *(global_gpio+GPCLR0);
		set0_value |= (1<<4);
		*(global_gpio+GPCLR0) = set0_value;
		printk(KERN_ERR"1 write led_value =0x%x \n",set0_value);
	}
	printk(KERN_INFO"led_write end \n");
	return 0;
}
 static struct file_operations led_ops = {

.owner    =  THIS_MODULE,
.open = led_open,
.read = led_read,
.write = led_write,
};
static int __init led_init(void)
{
	int ret;
	printk (KERN_INFO"global_gpio = 0x%lx\n", (unsigned long)global_gpio);
	global_gpio = ioremap(BCM2711_GPIO_BASE, 0x80);
	printk (KERN_INFO"global_gpio = 0x%lx\n", (unsigned long)global_gpio);
	ret = alloc_chrdev_region(&devno,0,1,"ledzfj");
	printk(KERN_INFO"ret= %d\n", ret);
	printk(KERN_INFO"devno= 0x%x\n", devno);
	major=MAJOR(devno);
	minor=MINOR(devno);
	printk(KERN_INFO"major = %d \n",major);
	printk(KERN_INFO"minor = %d \n",minor);
	cdev_init(&led_dev, &led_ops);
	led_dev.owner=THIS_MODULE;
	ret = cdev_add(&led_dev,devno,1); // 把这个驱动加入到内核的链表中
	cls = class_create(THIS_MODULE, "ledclass");//   注册class 让代码在dev自动生成设备  
   	if(IS_ERR(cls))
	{
		cdev_del(&led_dev);
		return -1;
	}
	test_device = device_create(cls,NULL,devno,NULL,"ledzfj");创建设备文件/dev/ledzfj
	if(IS_ERR(test_device))
	{
		class_destroy(cls);
		cdev_del(&led_dev);
		return -1;
	}
   printk(KERN_INFO"led init ok!\n");
   return 0;
   }
   static void __exit led_exit(void)
   {
iounmap(global_gpio);
device_destroy(cls,devno);
class_destroy(cls);
cdev_del(&led_dev);
    unregister_chrdev_region(devno, 1);   
printk(KERN_INFO"led_exit \n");
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
